home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxd / ModemConfig.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  12KB  |  344 lines

  1. /*    $Header: /usr/people/sam/fax/faxd/RCS/ModemConfig.c++,v 1.37 1994/03/29 20:20:54 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "ModemConfig.h"
  26. #include "t.30.h"
  27. #include <string.h>
  28. #include <syslog.h>
  29.  
  30. ModemConfig::ModemConfig()
  31.     : type("unknown")
  32.     , dialCmd("DT%s")            // %s = phone number
  33.     , noAutoAnswerCmd("S0=0")
  34.     , echoOffCmd("E0")
  35.     , verboseResultsCmd("V1")
  36.     , resultCodesCmd("Q0")
  37.     , onHookCmd("H0")
  38.     , softResetCmd("Z")
  39.     , waitTimeCmd("S7=30")        // wait time is 30 seconds
  40.     , pauseTimeCmd("S8=2")        // comma pause time is 2 seconds
  41.     , class1Cmd("+FCLASS=1")        // set class 1 (fax)
  42. {
  43.     class2XmitWaitForXON = FALSE;    // default suits most Class 2 modems
  44.  
  45.     // default volume setting commands
  46.     setVolumeCmds("M0 L0M1 L1M1 L2M1 L3M1");
  47.  
  48.     answerAnyCmd = "A";
  49.  
  50.     flowControl = FaxModem::FLOW_XONXOFF;// expect XON/XOFF flow control
  51.     maxRate = FaxModem::BR19200;    // reasonable for most modems
  52.     sendFillOrder = FILLORDER_LSB2MSB;    // default to CCITT bit order
  53.     recvFillOrder = FILLORDER_LSB2MSB;    // default to CCITT bit order
  54.     frameFillOrder = FILLORDER_LSB2MSB;    // default to CCITT bit order
  55.     hostFillOrder = FILLORDER_MSB2LSB;    // default to most common
  56.  
  57.     resetDelay = 2600;            // 2.6 second delay after reset
  58.     baudRateDelay = 0;            // delay after setting baud rate
  59.  
  60.     t1Timer = TIMER_T1;            // T.30 T1 timer (ms)
  61.     t2Timer = TIMER_T2;            // T.30 T2 timer (ms)
  62.     t4Timer = TIMER_T4;            // T.30 T4 timer (ms)
  63.     dialResponseTimeout = 3*60*1000;    // dialing command timeout (ms)
  64.     answerResponseTimeout = 3*60*1000;    // answer command timeout (ms)
  65.     pageStartTimeout = 3*60*1000;    // page send/receive timeout (ms)
  66.     pageDoneTimeout = 3*60*1000;    // page send/receive timeout (ms)
  67.  
  68.     class1TCFResponseDelay = 75;    // 75ms delay between TCF and ack/nak
  69.     class1SendPPMDelay = 75;        // 75ms delay before sending PPM
  70.     class1SendTCFDelay = 75;        // 75ms delay between sending DCS & TCF
  71.     class1TrainingRecovery = 1500;    // 1.5sec delay after failed training
  72.     class1RecvAbortOK = 200;        // 200ms after abort before flushing OK
  73.     class1FrameOverhead = 4;        // flags + station id + 2-byte FCS
  74.     class1RecvIdentTimer = t1Timer;    // default to standard protocol
  75.  
  76.     maxPacketSize = 16*1024;        // max write to modem
  77.     interPacketDelay = 0;        // delay between modem writes
  78.     waitForConnect = FALSE;        // unique answer response from modem
  79. }
  80.  
  81. ModemConfig::~ModemConfig()
  82. {
  83. }
  84.  
  85. #ifdef streq
  86. #undef streq
  87. #endif
  88. #define    streq(a,b)    (strcasecmp(a,b)==0)
  89.  
  90. static fxBool getBoolean(const char* cp)
  91.     { return (streq(cp, "on") || streq(cp, "yes")); }
  92.  
  93. static BaudRate
  94. findRate(const char* cp)
  95. {
  96.     static const struct {
  97.     const char* name;
  98.     BaudRate    br;
  99.     } rates[] = {
  100.     {   "300", FaxModem::BR300 },
  101.     {  "1200", FaxModem::BR1200 },
  102.     {  "2400", FaxModem::BR2400 },
  103.     {  "4800", FaxModem::BR4800 },
  104.     {  "9600", FaxModem::BR9600 },
  105.     { "19200", FaxModem::BR19200 },
  106.     { "38400", FaxModem::BR38400 },
  107.     { "57600", FaxModem::BR57600 },
  108.     { "76800", FaxModem::BR76800 },
  109.     };
  110.  
  111. #define    N(a)    (sizeof (a) / sizeof (a[0]))
  112.     for (int i = N(rates)-1; i >= 0; i--)
  113.     if (streq(cp, rates[i].name))
  114.         return (rates[i].br);
  115.     return (FaxModem::BR0);
  116. #undef    N
  117. }
  118.  
  119. static BaudRate
  120. getRate(const char* cp)
  121. {
  122.     BaudRate br = findRate(cp);
  123.     if (br == FaxModem::BR0) {
  124.     syslog(LOG_ERR, "Unknown baud rate \"%s\", using 19200", cp);
  125.     br = FaxModem::BR19200;            // default
  126.     }
  127.     return (br);
  128. }
  129.  
  130. static u_int
  131. getFill(const char* cp)
  132. {
  133.     if (streq(cp, "LSB2MSB"))
  134.     return (FILLORDER_LSB2MSB);
  135.     else if (streq(cp, "MSB2LSB"))
  136.     return (FILLORDER_MSB2LSB);
  137.     else {
  138.     syslog(LOG_ERR, "Unknown fill order \"%s\"", cp);
  139.         return ((u_int) -1);
  140.     }
  141. }
  142.  
  143. static FlowControl
  144. getFlow(const char* cp)
  145. {
  146.     if (streq(cp, "xonxoff"))
  147.     return (FaxModem::FLOW_XONXOFF);
  148.     else if (streq(cp, "rtscts"))
  149.     return (FaxModem::FLOW_RTSCTS);
  150.     else {
  151.     syslog(LOG_ERR, "Unknown flow control \"%s\", using xonxoff", cp);
  152.     return (FaxModem::FLOW_XONXOFF);    // default
  153.     }
  154. }
  155.  
  156. void
  157. ModemConfig::setVolumeCmds(const fxStr& tag)
  158. {
  159.     u_int l = 0;
  160.     for (int i = FaxModem::OFF; i <= FaxModem::HIGH; i++) {
  161.     fxStr tmp = tag.token(l, " \t");        // NB: for gcc
  162.     setVolumeCmd[i] = parseATCmd(tmp);
  163.     }
  164. }
  165.  
  166. /*
  167.  * Scan AT command strings and convert <...> escape
  168.  * commands into single-byte escape codes that are
  169.  * interpreted by FaxModem::atCmd.  Note that the
  170.  * baud rate setting commands are carefully ordered
  171.  * so that the desired baud rate can be extracted
  172.  * from the low nibble.
  173.  */
  174. fxStr
  175. ModemConfig::parseATCmd(const char* cp)
  176. {
  177.     fxStr cmd(cp);
  178.     u_int pos = 0;
  179.     while ((pos = cmd.next(pos, '<')) != cmd.length()) {
  180.     u_int epos = pos+1;
  181.     fxStr esc = cmd.token(epos, '>');
  182.     esc.lowercase();
  183.  
  184.     char ecode;
  185.     if (esc == "xon")
  186.         ecode = ESC_XON;
  187.     else if (esc == "rts")
  188.         ecode = ESC_RTS;
  189.     else if (esc == "")        // NB: "<>" => <
  190.         ecode = '<';
  191.     else {
  192.         BaudRate br = findRate(esc);
  193.         if (br == FaxModem::BR0) {
  194.         syslog(LOG_ERR, "Unknown AT escape code \"%s\"", (char*) esc);
  195.         pos = epos;
  196.         continue;
  197.         }
  198.         ecode = 0x80|ord(br);
  199.     }
  200.     cmd.remove(pos, epos-pos);
  201.     cmd.insert(ecode, pos);
  202.     }
  203.     return (cmd);
  204. }
  205.  
  206. /*
  207.  * The following tables map configuration parameter names to
  208.  * pointers to class ModemConfig members.
  209.  */
  210. static const struct {
  211.     const char*         name;
  212.     fxStr ModemConfig::* p;
  213. } atcmds[] = {
  214.     { "ModemAnswerCmd",            &ModemConfig::answerAnyCmd },
  215.     { "ModemAnswerAnyCmd",        &ModemConfig::answerAnyCmd },
  216.     { "ModemAnswerFaxCmd",        &ModemConfig::answerFaxCmd },
  217.     { "ModemAnswerDataCmd",        &ModemConfig::answerDataCmd },
  218.     { "ModemAnswerVoiceCmd",        &ModemConfig::answerVoiceCmd },
  219.     { "ModemAnswerFaxBeginCmd",        &ModemConfig::answerFaxBeginCmd },
  220.     { "ModemAnswerDataBeginCmd",    &ModemConfig::answerDataBeginCmd },
  221.     { "ModemAnswerVoiceBeginCmd",    &ModemConfig::answerVoiceBeginCmd },
  222.     { "ModemResetCmds",            &ModemConfig::resetCmds },
  223.     { "ModemResetCmd",            &ModemConfig::resetCmds },
  224.     { "ModemDialCmd",            &ModemConfig::dialCmd },
  225.     { "ModemFlowControlCmd",        &ModemConfig::flowControlCmd },
  226.     { "ModemSetupAACmd",        &ModemConfig::setupAACmd },
  227.     { "ModemSetupDTRCmd",        &ModemConfig::setupDTRCmd },
  228.     { "ModemSetupDCDCmd",        &ModemConfig::setupDCDCmd },
  229.     { "ModemNoAutoAnswerCmd",        &ModemConfig::noAutoAnswerCmd },
  230.     { "ModemEchoOffCmd",        &ModemConfig::echoOffCmd },
  231.     { "ModemVerboseResultsCmd",        &ModemConfig::verboseResultsCmd },
  232.     { "ModemResultCodesCmd",        &ModemConfig::resultCodesCmd },
  233.     { "ModemOnHookCmd",            &ModemConfig::onHookCmd },
  234.     { "ModemSoftResetCmd",        &ModemConfig::softResetCmd },
  235.     { "ModemWaitTimeCmd",        &ModemConfig::waitTimeCmd },
  236.     { "ModemCommaPauseTimeCmd",        &ModemConfig::pauseTimeCmd },
  237.     { "ModemMfrQueryCmd",        &ModemConfig::mfrQueryCmd },
  238.     { "ModemModelQueryCmd",        &ModemConfig::modelQueryCmd },
  239.     { "ModemRevQueryCmd",        &ModemConfig::revQueryCmd },
  240.     { "Class1Cmd",            &ModemConfig::class1Cmd },
  241.     { "Class2Cmd",            &ModemConfig::class2Cmd },
  242.     { "Class2BORCmd",            &ModemConfig::class2BORCmd },
  243.     { "Class2RELCmd",            &ModemConfig::class2RELCmd },
  244.     { "Class2CQCmd",            &ModemConfig::class2CQCmd },
  245.     { "Class2AbortCmd",            &ModemConfig::class2AbortCmd },
  246.     { "Class2DCCQueryCmd",        &ModemConfig::class2DCCQueryCmd },
  247.     { "Class2TBCCmd",            &ModemConfig::class2TBCCmd },
  248.     { "Class2CRCmd",            &ModemConfig::class2CRCmd },
  249.     { "Class2PHCTOCmd",            &ModemConfig::class2PHCTOCmd },
  250.     { "Class2BUGCmd",            &ModemConfig::class2BUGCmd },
  251.     { "Class2LIDCmd",            &ModemConfig::class2LIDCmd },
  252.     { "Class2DCCCmd",            &ModemConfig::class2DCCCmd },
  253.     { "Class2DISCmd",            &ModemConfig::class2DISCmd },
  254.     { "Class2CIGCmd",            &ModemConfig::class2CIGCmd },
  255.     { "Class2SPLCmd",            &ModemConfig::class2SPLCmd },
  256.     { "Class2PIECmd",            &ModemConfig::class2PIECmd },
  257.     { "Class2NRCmd",            &ModemConfig::class2NRCmd },
  258. };
  259. static const struct {
  260.     const char*         name;
  261.     u_int ModemConfig::* p;
  262. } fillorders[] = {
  263.     { "ModemRecvFillOrder",        &ModemConfig::recvFillOrder },
  264.     { "ModemSendFillOrder",        &ModemConfig::sendFillOrder },
  265.     { "ModemFrameFillOrder",        &ModemConfig::frameFillOrder },
  266.     { "ModemHostFillOrder",        &ModemConfig::hostFillOrder },
  267. };
  268. static const struct {
  269.     const char*         name;
  270.     u_int ModemConfig::* p;
  271. } numbers[] = {
  272.     { "ModemResetDelay",        &ModemConfig::resetDelay },
  273.     { "ModemBaudRateDelay",        &ModemConfig::baudRateDelay },
  274.     { "ModemMaxPacketSize",        &ModemConfig::maxPacketSize },
  275.     { "ModemInterPacketDelay",        &ModemConfig::interPacketDelay },
  276.     { "FaxT1Timer",            &ModemConfig::t1Timer },
  277.     { "FaxT2Timer",            &ModemConfig::t2Timer },
  278.     { "FaxT4Timer",            &ModemConfig::t4Timer },
  279.     { "ModemDialResponseTimeout",    &ModemConfig::dialResponseTimeout },
  280.     { "ModemAnswerResponseTimeout",    &ModemConfig::answerResponseTimeout },
  281.     { "ModemPageStartTimeout",        &ModemConfig::pageStartTimeout },
  282.     { "ModemPageDoneTimeout",        &ModemConfig::pageDoneTimeout },
  283.     { "Class1TCFResponseDelay",        &ModemConfig::class1TCFResponseDelay },
  284.     { "Class1SendPPMDelay",        &ModemConfig::class1SendPPMDelay },
  285.     { "Class1SendTCFDelay",        &ModemConfig::class1SendTCFDelay },
  286.     { "Class1TrainingRecovery",        &ModemConfig::class1TrainingRecovery },
  287.     { "Class1RecvAbortOK",        &ModemConfig::class1RecvAbortOK },
  288.     { "Class1FrameOverhead",        &ModemConfig::class1FrameOverhead },
  289.     { "Class1RecvIdentTimer",        &ModemConfig::class1RecvIdentTimer },
  290. };
  291.  
  292. fxBool
  293. ModemConfig::parseItem(const char* tag, const char* value)
  294. {
  295.     int i;
  296.  
  297. #define    N(a)    (sizeof (a) / sizeof (a[0]))
  298.     for (i = N(atcmds)-1; i >= 0; i--)
  299.     if (streq(tag, atcmds[i].name)) {
  300.         (*this).*atcmds[i].p = parseATCmd(value);
  301.         return (TRUE);
  302.     }
  303.     for (i = N(fillorders)-1; i >= 0 ; i--)
  304.     if (streq(tag, fillorders[i].name)) {
  305.         (*this).*fillorders[i].p = getFill(value);
  306.         return (TRUE);
  307.     }
  308.     for (i = N(numbers)-1; i >= 0 ; i--)
  309.     if (streq(tag, numbers[i].name)) {
  310.         (*this).*numbers[i].p = atoi(value);
  311.         return (TRUE);
  312.     }
  313. #undef N
  314.     fxBool recognized = TRUE;
  315.     if (streq(tag, "ModemType"))
  316.     type = value;
  317.     else if (streq(tag, "ModemSetVolumeCmd"))
  318.     setVolumeCmds(value);
  319.     else if (streq(tag, "ModemFlowControl"))
  320.     flowControl = getFlow(value);
  321.     else if (streq(tag, "ModemMaxRate") || streq(tag, "ModemRate"))
  322.     maxRate = getRate(value);
  323.     else if (streq(tag, "ModemWaitForConnect"))
  324.     waitForConnect = getBoolean(value);
  325.  
  326.     // Class 2-specific configuration controls
  327.     else if (streq(tag, "Class2RecvDataTrigger"))
  328.     class2RecvDataTrigger = value;
  329.     else if (streq(tag, "Class2XmitWaitForXON"))
  330.     class2XmitWaitForXON = getBoolean(value);
  331.  
  332.     // for backwards compatibility
  333.     else if (streq(tag, "WaitForCarrier"))
  334.     waitTimeCmd = "S7=" | fxStr(value);
  335.     else if (streq(tag, "CommaPauseTime"))
  336.     pauseTimeCmd = "S8=" | fxStr(value);
  337.     else if (streq(tag, "ModemXONXOFF"))    // old way
  338.     flowControl = (getBoolean(value) ?
  339.             FaxModem::FLOW_XONXOFF : FaxModem::FLOW_RTSCTS);
  340.     else
  341.     recognized = FALSE;
  342.     return (recognized);
  343. }
  344.